package com.example.demo.web;

import com.example.demo.annotation.CurrentUser;
import com.example.demo.annotation.Limit;
import com.example.demo.bean.Dept;
import com.example.demo.bean.User;
import com.example.demo.common.ResponseResult;
import com.example.demo.common.ResponseResultCode;
import com.example.demo.common.ResponseResultFactory;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author lyc
 * @desc 参数解析 都是通过内部参数解析器 完成类型转换 的 传过来的其实都是字符串
 *
 * 三种写法,test(String name),
  test(@RequestParam String name),
  test(@RequestParam("userName") String name),
  第一种如果没有name 参数不会报错，
  第二种没有name 参数会报错，（也可以设置required = false),
  第三种跟第二种的区别是name 参数换为userName。
 * @date 2019/6/3.
 */
@RestController
@Slf4j
public class DeptAction {

    @Autowired(required = false)
    private RedissonClient redissonClient;


    /**
     * 常规类型匹配
     * @param name 字符串
     * @param leader 0，false 都会解析成false 1 或者true 都会解析 true
     * @param id
     * @param age
     * @param price
     * @param em 枚举类型 如传 SUCCESS 串自己定义的枚举大写
     * @return
     */
    @Limit(key = "test", period = 100, count = 10)
    @PostMapping("dept/update")
    @ResponseBody
    public ResponseResult updateDept(String name, Boolean leader, Integer id
                                    , Double age, BigDecimal price, ResponseResultCode em){

        return ResponseResultFactory.success("添加成功");
    }

    /**
     * 集合类型 必须加 RequestParam 注解 不然报错  No primary or default constructor found for interface
     * @param ids 可以是 传 1,2,3 逗号分隔 也可以 ids=1&ids=2 但是不能混合传 解析器问题
     * @return
     */
    @PostMapping("dept/update/ids")
    public ResponseResult updateDept(@RequestParam(value = "ids") List<Integer> ids){

        return ResponseResultFactory.success("添加成功");
    }

    /**
     * 数组和和集合一样
     * @param ids
     * @return
     */
    @PostMapping("dept/update/ids1")
    public ResponseResult updateDept(@RequestParam(value = "ids") Integer[] ids){
        int i = 0;
        int sum = 2/i;
        return ResponseResultFactory.success("添加成功");
    }

    /**
     * map 必须加上 @RequestParam 注解 不然 没数据 看上去map 万能接受 但是不推荐使用(除非不知道前端字段可以考虑)
     * @param map
     * @return
     */
    @PostMapping("dept/update/map")
    public ResponseResult updateDeptMap(@RequestParam Map map){

        return ResponseResultFactory.success("添加成功");
    }
    /**
     * 普通对象类型
     * @param user 如 id=12&name=小明 简单传就行
     * @return
     */
    @PostMapping("dept/addUser")
    public ResponseResult addDept(User user){

        return ResponseResultFactory.success("添加用户");
    }

    /**
     * 复杂对象 @RequestParam 不要用这个注解 不然匹配不上名字
     * @param dept users[0].name=aaa&users[0].age=12&users[1].name=13&users[1].age=12&deptName=呵呵呵&ids=1,2,3
     * @return
     */
    @PostMapping("dept/Dept")
    public ResponseResult addDept(Dept dept){

        return ResponseResultFactory.success("添加用户");
    }


    /**
     * 集合对象 这种不支持表单方式 考虑上面一种复杂对象处理方式 或者下面一种 dept/users1
     * https://www.cnblogs.com/breath-taking/articles/5764751.html
     * https://zhidao.baidu.com/question/497980960120285884.html
     * @param users
     * @return
     */
    @PostMapping("dept/users")
    public ResponseResult addDept(@RequestParam(value = "users")List<User> users){

        return ResponseResultFactory.success("添加用户");
    }

    /**
     * 集合对象
     * @param users
     * @return
     */
    @PostMapping("dept/users1")
    public ResponseResult addDept1(String users){
        // 在转换一次 json 工具
        return ResponseResultFactory.success("添加用户");
    }

    /**
     * ===============================上面都是表单格式默认 为application/x-wwww-from-urlencoded 提交================================================
     * =================================下面 都是 json 格式application/json 其实就是内部jackson 序列化对象================================================================
     */
    /**
     * 对象
     *  header格式 content-type:"application/json charset=utf-8", 参数 直接json 格式
     *  {"id": 1,name": "demoData","age": 1,"pthone": "demoData",email": "demoData"}
     *
     *   $.ajax({
     url: "srarch_data/search_data_detail.action",
     type: "post",
     dataType:'json',
     contentType : 'application/json;charset=utf-8',
     data:  JSON.stringify(obj),
     success: function (json) {

     }
     });
     * @param user
     * @return
     */
    @PostMapping("addUser")
    public ResponseResult addUser(@RequestBody User user){

        return ResponseResultFactory.success("添加用户");
    }

    /**
     * 集合
     * @param users  [{"id": 1,"name": "demoData","age": 1,"pthone": "demoData","email": "demoData"},{"id": 1,"name": "demoData","age": 1,"pthone": "demoData","email": "demoData"}]
     * @return
     */
    @PostMapping("addUsers")
    public ResponseResult addUsers(@RequestBody List<User> users){

        return ResponseResultFactory.success("添加用户");
    }


    /**
     *复杂对象 传递
     * {
     "id": 1,
     "deptName": "demoData",
     "users": [{
     "id": 1,
     "name": "demoData",
     "age": 1,
     "pthone": "demoData",
     "email": "demoData"
     }],
     "createDate": "demoData",
     "updateTime": "2019/6/3 12:12",
     "ids": [
     1
     ]
     }
     * @param dept
     * @return
     */
    @PostMapping("addDept")
    public ResponseResult addDept2(@RequestBody Dept dept){

        return ResponseResultFactory.success("添加用户",dept);
    }

    /**
     *  可以格式任意数据 @RequestParam 这个注解 可以不要 如果加了 @RequestBody 但是表单格式必须加  @RequestParam
     * @param dept
     * @return
     */
    @PostMapping("addDeptMap")
    public ResponseResult addDept3(@RequestParam @RequestBody Map dept){

        return ResponseResultFactory.success("添加用户",dept);
    }

    /**
     * ================================== 表单模式和 json 格式混用 header 还是application/json  url 上带参数 =====================================
     */
    /**
     * 混合模式 基本很少人折磨用 但是可以用
     * @param user
     * @param id
     *
     * 例如 /mix?id=12  {"id": 1,"name": "demoData","age": 1,"pthone": "demoData","email": "demoData"}
     * @return
     */
    @PostMapping("mix")
    public ResponseResult mix(@RequestBody User user,Integer id){

        return ResponseResultFactory.success("添加用户");
    }


    /**
     * ========================================== 序列化 与反序列化 =====================================================
     */
    /**
     * 序列化与反序列 化
     * @param user
     * @return
     */
    @PostMapping("edit/user")
    public ResponseResult editUser(@RequestBody User user){

        return ResponseResultFactory.success("添加用户",user);
    }



    /**
     * 日期格式参数绑定
     * @param date
     * @return
     */
    @PostMapping("edit/date")
    public ResponseResult editDate(Date date){
        return ResponseResultFactory.success("添加用户",date);
    }

    /**
     * 局部使用  类似 注解在对象上 @DateTimeFormat(pattern = "yyyy/MM/dd HH:ss")   //入参 spring 注解 格式化时间 可参考全局配置
     * @param binder
     */
    /*@InitBinder
    public void initBinder(WebDataBinder binder){
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }*/

    /**
     * 自定义 解析器
     * @param user
     * @return
     */
    @PostMapping("edit/users2")
    public ResponseResult editUser2(@CurrentUser String user){
        return ResponseResultFactory.success("添加用户",user);
    }

}